﻿using System;
using PostSharp.Laos;
using Castle.Windsor;
using DDDProject.Aspects.Utils;
using log4net;

namespace DDDProject.Aspects
{
    [Serializable]
    public class InjectComponentAttribute : OnFieldAccessAspect
    {
        private static readonly ILog _log = LogManager.GetLogger(typeof(InjectComponentAttribute));

        public override void OnGetValue(FieldAccessEventArgs args)
        {
            if (args.ExposedFieldValue == null)
            {
                // Retrieve IoC container
                IWindsorContainer container = CastleUtils.GetWindsorContainer();

                // Retrieve instance to inject
                Object instance = null;

                try
                {
                    _log.Debug("Retrieving component instance of type " + args.FieldInfo.FieldType.AssemblyQualifiedName);

                    instance = container.Resolve(args.FieldInfo.FieldType);

                    _log.Debug("Component instance retrieved !");
                }
                catch (Exception ex)
                {
                    _log.Error("Error retrieving component instance", ex);

                    throw new InvalidOperationException(String.Format(
                                "It seems that the type {0} is not registered in your container.", args.FieldInfo.FieldType));
                }

                _log.Debug("Setting field with component instance...");

                // Set field value
                args.StoredFieldValue = args.ExposedFieldValue = instance;

                _log.Debug("Field set with component instance of type " + args.FieldInfo.FieldType.AssemblyQualifiedName);
            }
        }

        public override void OnSetValue(FieldAccessEventArgs args)
        {
            // Do nothing...
        }
    }
}
